package com.vains.service.impl;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.vains.bean.Result;
import com.vains.bean.exception.GatewayException;
import com.vains.client.UserClient;
import com.vains.constant.RedisKeyConstants;
import com.vains.dto.GrantedAuthorityDto;
import com.vains.entity.OauthUser;
import com.vains.util.JsonUtils;
import lombok.AllArgsConstructor;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 框架服务实现，登录时security自动调用
 *
 * @author vains
 * @date 2021/4/3 1:28
 */
@AllArgsConstructor
@Service("userDetailsServiceImpl")
public class UserDetailsServiceImpl implements UserDetailsService {

    private final UserClient userClient;

    private final StringRedisTemplate stringRedisTemplate;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        String key = RedisKeyConstants.KEY_USER_INFO_PREV + username;
        String s = stringRedisTemplate.opsForValue().get(key);
        if (!StringUtils.isEmpty(s)) {
            OauthUser oauthUser = JsonUtils.jsonCovertToObject(s, OauthUser.class);
            return new User(username, oauthUser.getUserPassword(), oauthUser.getAuthorities());
        }
        Result<OauthUser> result = userClient.loadUserByUsername(username);
        if (result == null) {
            throw new GatewayException("调用用户服务异常.");
        }
        if (!result.getSuccess()) {
            throw new RuntimeException("获取用户信息失败，原因：" + result.getMessage());
        }
        OauthUser oauthUser = result.getData();
        if (!oauthUser.getUserEnabled()) {
            throw new RuntimeException("用户已被禁用");
        }
        Result<List<String>> listResult = userClient.findPermissionsByUserId(oauthUser.getUserId());
        if (listResult == null) {
            throw new GatewayException("调用用户服务异常.");
        }
        if (!result.getSuccess()) {
            throw new RuntimeException("获取用户权限信息失败，原因：" + result.getMessage());
        }
        List<String> authorities = listResult.getData();
        Set<GrantedAuthorityDto> simpleGrantedAuthorities = new HashSet<>();
        if (CollectionUtils.isNotEmpty(authorities)) {
            authorities = authorities.stream().filter(e -> !StringUtils.isEmpty(e)).collect(Collectors.toList());
            authorities.forEach(e -> simpleGrantedAuthorities.add(new GrantedAuthorityDto(e)));
        }
        oauthUser.setAuthorities(simpleGrantedAuthorities);
        stringRedisTemplate.opsForValue().set(key, JsonUtils.objectCovertToJson(oauthUser));
        return new User(username, oauthUser.getUserPassword(), simpleGrantedAuthorities);
    }
}
